class Promise {
    static #pending = 'pending';
    static #fulfilled = 'fulfilled';
    static #rejected = 'rejected';

    constructor(executor) {
        // 添加属性
        this.PromiseState = Promise.#pending;
        this.PromiseResult = null;
        this.callbacks = [];
        // 保存实例对象的this
        const self = this;

        /**
         * resolve函数
         * @param data
         */
        function resolve(data) {
            if (self.PromiseState !== Promise.#pending) {
                // 如果不是pending，则返回
                return;
            }

            // 1.修改对象的状态（promiseState）
            self.PromiseState = Promise.#fulfilled; // 也可以是“resolved”
            // 2.设置对象的结果值（promiseResult）
            self.PromiseResult = data;
            // 3.执行callback
            setTimeout(() => {
                self.callbacks.forEach((item) => {
                    item.onResolved(data);
                });
            });
        }

        /**
         * reject函数
         * @param data
         */
        function reject(data) {
            if (self.PromiseState !== Promise.#pending) {
                // 如果不是pending，则返回
                return;
            }

            // 1.修改对象的状态（promiseState）
            self.PromiseState = Promise.#rejected;
            // 2.设置对象的结果值（promiseResult）
            self.PromiseResult = data;
            // 3.执行callback
            setTimeout(() => {
                self.callbacks.forEach((item) => {
                    item.onRejected(data);
                });
            });
        }

        try {
            // 同步调用【执行器函数】
            executor(resolve, reject);
        } catch (e) {
            // 修改promiseState为失败
            reject(e);
        }
    }

    then(onResolved, onRejected) {
        const self = this;
        // 判断回调函数参数，用于异常穿透
        if (typeof onRejected !== 'function') {
            onRejected = (err) => {
                throw err;
            }
        }
        // 值传递
        if (typeof onResolved !== 'function') {
            onResolved = (val) => {
                return val;
            }
        }

        return new Promise((resolve, reject) => {
            switch (this.PromiseState) {
                case Promise.#fulfilled: {
                    Promise.#timedMinion(onResolved, self.PromiseResult, resolve, reject);
                    break;
                }
                case Promise.#rejected: {
                    Promise.#timedMinion(onRejected, self.PromiseResult, resolve, reject);
                    break;
                }
                case Promise.#pending: {
                    // 保存回调函数
                    this.callbacks.push({
                        onResolved: function () {
                            Promise.#minion(onResolved, self.PromiseResult, resolve, reject);
                        },
                        onRejected: function () {
                            Promise.#minion(onRejected, self.PromiseResult, resolve, reject);
                        }
                    });
                    break;
                }
                default:
                    break;
            }
        });
    }

    catch(onRejected) {
        return this.then(undefined, onRejected);
    }

    static resolve(val) {
        return new Promise((resolve, reject) => {
            Promise.#smallMinion(val, resolve, reject);
        });
    }

    static reject(err) {
        return new Promise((resolve, reject) => {
            reject(err);
        });
    }

    static all(promises) {
        return new Promise((resolve, reject) => {
            let count = 0;
            let res = [];
            for (let i = 0; i < promises.length; i++) {
                promises[i].then((val) => {
                    count++;
                    res[i] = val;
                    if (count === promises.length) {
                        resolve(res);
                    }
                }, (err) => {
                    reject();
                });
            }
        });
    }

    static race(promises) {
        return new Promise((resolve, reject) => {
            for (let i = 0; i < promises.length; i++) {
                promises[i].then((val) => {
                    resolve(val);
                }, (err) => {
                    reject(err);
                });
            }
        });
    }

    /**
     *
     * @param onStateChanged {function} onResolved, onRejected
     * @param promiseResult self.PromiseResult
     * @param resolve {function} resolve
     * @param reject {function} reject
     */
    static #timedMinion(onStateChanged, promiseResult, resolve, reject) {
        setTimeout(() => {
            Promise.#minion(onStateChanged, promiseResult, resolve, reject);
        });
    }

    /**
     *
     * @param onStateChanged {function} onResolved, onRejected
     * @param promiseResult self.PromiseResult
     * @param resolve {function} resolve
     * @param reject {function} reject
     */
    static #minion(onStateChanged, promiseResult, resolve, reject) {
        try {
            let res = onStateChanged(promiseResult);
            this.#smallMinion(res, resolve, reject);
        } catch (e) {
            reject(e);
        }
    }

    /**
     *
     * @param val
     * @param resolve {function}
     * @param reject {function}
     */
    static #smallMinion(val, resolve, reject) {
        if (val instanceof Promise) {
            val.then((val) => {
                resolve(val);
            }, (err) => {
                reject(err);
            });
        } else {
            resolve(val);
        }
    }
}